/*++

Copyright (c) 2014 Minoca Corp.

    This file is licensed under the terms of the GNU General Public License
    version 3. Alternative licensing terms are available. Contact
    info@minocacorp.com for details. See the LICENSE file at the root of this
    project for complete licensing information.

Module Name:

    entry.s

Abstract:

    This module implements the initial entry point into the ARMv7 firmware. Its
    job is to do essential initialization and call the C main function.

Author:

    Evan Green 19-Dec-2014

Environment:

    Firmware

--*/

//
// ------------------------------------------------------------------- Includes
//

#include <minoca/kernel/arm.inc>

//
// ---------------------------------------------------------------- Definitions
//

.equ STACK_SIZE,    0x4000

//
// ----------------------------------------------------------------------- Code
//

//
// .text specifies that this code belongs in the executable section. This is
// the only section in the MBR code, data also lives in the text section.
// .arm specifies that this code should be compiled in ARM mode.
//

.text
.arm

//
// Stick this in the .init section so it ends up at the front of the binary.
//

.section .init

//
// .global allows this label to be visible to the linker. _start is the entry
// point to the MBR code, so it needs to be globally visible.
//

.global _start

//
// This is the entry point for the ARM boot loader. It changes to SVC mode,
// sets up the initial stack, and jumps to the main loader.
//

_start:

    //
    // Save the boot device type argument.
    //

    mov     %r4, %r0

    //
    // Disable interrupts and switch to SVC mode.
    //

    mov     %r2, #(PSR_FLAG_IRQ | ARM_MODE_SVC)
    msr     CPSR_c, %r2

    //
    // Flip some essential MMU bits allowing unaligned accesses.
    //

    mrc     p15, 0, %r0, %cr1, %cr0, 0
    bic     %r0, %r0, #MMU_ALIGNMENT_FAULT_ENABLED
    orr     %r0, %r0, #MMU_UNALIGNED_ACCESS_ENABLED
    mcr     p15, 0, %r0, %cr1, %cr0, 0

    //
    // Zero out the BSS section.
    //

    ldr     %r1, =__bss_start__
    ldr     %r2, =__bss_end__
    mov     %r0, #0

BssZeroLoop:
    str     %r0, [%r1], #4
    cmp     %r1, %r2
    blt     BssZeroLoop

    //
    // The stack starts at the image base and works downwards.
    //

    adr     %r0, _start             @ Get the current address for the stack top.
    ldr     %r1, =STACK_SIZE        @ Get the stack size.
    mov     %r2, %r4                @ Get the boot device type.
    mov     %sp, %r0                @ Set the stack.
    mov     %r11, #0                @ Zero the ARM frame pointer.
    mov     %r7, #0                 @ Zero out the Thumb frame pointer.
    mov     %r3, %r7                @ Zero out another temporary register.
    push    {%r3, %r7}              @ Create an empty stack frame for debugging.
    blx     EfiBeagleBoneMain

LoopForever:
    b       LoopForever

